#include "blockPool.h"
#include "mathFunc.h"
#include "assert.h"
#include <iostream>

blockPool::blockPool(octNode* root, int blockSize):_root(root),_blockSize(blockSize)
{
}

void blockPool::generateBlockPacking()
{
	_blockPoolDim = nearest3root(_root->getBlockNumInSubTree() - _root->getNonLeafBlockNumInSubTree());

	_blockPool = new volume3D(_blockPoolDim*(_blockSize+1),_blockPoolDim*(_blockSize+1),_blockPoolDim*(_blockSize+1),_root->getVolume()->getVoxelByteSize(),0);

	static int count=0;
	blockPacking(_root, count);

}

void blockPool::generateFullResolutionLevelBlockPool()
{
	_blockPoolDim = nearest3root(_root->getBlockNumInSubTree());

	_blockPool = new volume3D(_blockPoolDim*(_blockSize+1),_blockPoolDim*(_blockSize+1),_blockPoolDim*(_blockSize+1),_root->getVolume()->getVoxelByteSize(),0);

	static int count=0;
	fullResolutionLevelBlockPacking(_root, count);

}

void blockPool::blockPacking(octNode* node, int &count)
{
	if(node->isLeaf() && !node->isSingleColor())
	{
		int indexZ = count/(_blockPoolDim*_blockPoolDim);
		int indexY = (count-indexZ*(_blockPoolDim*_blockPoolDim))/_blockPoolDim;
		int indexX = count - indexZ*(_blockPoolDim*_blockPoolDim) - indexY*_blockPoolDim;
#ifdef _NO_BOUNDARY
		vol->addSubVolume(node->getVolume(),indexZ*_blockSize, indexY*_blockSize, indexX*_blockSize);
#else
		assert(node->getVolume());
		_blockPool->addSubVolume(node->getVolume(),indexZ*(_blockSize+1), indexY*(_blockSize+1), indexX*(_blockSize+1));
#endif

		node->nodeInfo.blockPointer[0] = (indexX);
		node->nodeInfo.blockPointer[1] = (indexY);
		node->nodeInfo.blockPointer[2] = (indexZ);
		
		std::cout<<" ID "<<node->nodeInfo.ID<<"  count:"<<count<<
			"  index: "<<node->nodeInfo.blockPointer[2]<<
			" "<<node->nodeInfo.blockPointer[1]<<
			" "<<node->nodeInfo.blockPointer[0] <<std::endl;
		count++;
	}
	if(!node->isLeaf())
	{
			for(int k=0; k<2; k++)
				for (int j=0; j<2; j++)
					for(int i=0; i<2; i++)
					{
						blockPacking(node->getChild(k,j,i), count);
					}
	}

}

void blockPool::fullResolutionLevelBlockPacking(octNode *node, int &count)
{
	if(/*node->isLeaf() && */!node->isSingleColor())
	{
		int indexZ = count/(_blockPoolDim*_blockPoolDim);
		int indexY = (count-indexZ*(_blockPoolDim*_blockPoolDim))/_blockPoolDim;
		int indexX = count - indexZ*(_blockPoolDim*_blockPoolDim) - indexY*_blockPoolDim;
#ifdef _NO_BOUNDARY
		vol->addSubVolume(node->getVolume(),indexZ*_blockSize, indexY*_blockSize, indexX*_blockSize);
#else
		assert(node->getVolume());
		_blockPool->addSubVolume(node->getVolume(),indexZ*(_blockSize+1), indexY*(_blockSize+1), indexX*(_blockSize+1));
#endif

		node->nodeInfo.blockPointer[0] = (indexX);
		node->nodeInfo.blockPointer[1] = (indexY);
		node->nodeInfo.blockPointer[2] = (indexZ);
		
		std::cout<<" ID "<<node->nodeInfo.ID<<"  count:"<<count<<
			"  index: "<<node->nodeInfo.blockPointer[2]<<
			" "<<node->nodeInfo.blockPointer[1]<<
			" "<<node->nodeInfo.blockPointer[0] <<std::endl;
		count++;
	}
	if(!node->isLeaf())
	{
			for(int k=0; k<2; k++)
				for (int j=0; j<2; j++)
					for(int i=0; i<2; i++)
					{
						fullResolutionLevelBlockPacking(node->getChild(k,j,i), count);
					}
	}
}



bool blockPool::writeToFile(const char* filename)
{
	return _blockPool->writeToFile(filename);
}